package org.example.rowing.service;

import lombok.extern.slf4j.Slf4j;
import org.example.rowing.domain.Registration;
import org.example.rowing.domain.RegistrationWithAthlete;
import org.example.rowing.mapper.RegistrationMapper;
import org.example.rowing.mapper.RegistrationWithAthleteMapper;
import org.example.rowing.vo.AthleteVO;
import org.example.rowing.vo.CompositeKey;
import org.example.rowing.vo.RegistrationExportData;
import org.example.rowing.vo.RegistrationVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RegistrationInfoService {

    @Autowired
    private TeamInfoService teamInfoService;
    @Autowired
    private RegistrationMapper registrationMapper;
    @Autowired
    private RegistrationWithAthleteMapper registrationWithAthleteMapper;

    public List<RegistrationVO> showRegistrationsByRaceId(Long raceId) {
        List<RegistrationVO> registrationVOS = new ArrayList<>();
        if (raceId != null) {
            registrationVOS = registrationMapper.selectRegistrationVOByRaceId(raceId);
        }
        for (RegistrationVO registrationVO : registrationVOS) {
            RegistrationWithAthlete registrationWithAthleteCondition = new RegistrationWithAthlete();
            registrationWithAthleteCondition.setRegistrationId(registrationVO.getRegistrationId());
            List<RegistrationWithAthlete> athletes = registrationWithAthleteMapper.selectRegistrationWithAthleteByConditions(registrationWithAthleteCondition);
            registrationVO.setAthletes(athletes);
        }
        return registrationVOS;
    }

    public void saveOrUpdateRegistration(RegistrationVO registrationVO) {
        Registration registration = new Registration(registrationVO.getRegistrationId(),
                registrationVO.getRace().getId(), registrationVO.getTeam().getId());
        List<RegistrationWithAthlete> athletes = registrationVO.getAthletes();
        if (registration.getId() == null) {
            registrationMapper.insertRegistration(registration);
            log.info("新插入的报名信息id为： {}", registration.getId());
            for (RegistrationWithAthlete athlete : athletes) {
                athlete.setRegistrationId(registration.getId());
            }
            registrationWithAthleteMapper.batchInsertAthletes(athletes);
            log.info("报名信息已保存: {}, {}", registration, athletes);
        } else {
            registrationMapper.updateRegistration(registration);
            for (RegistrationWithAthlete athlete : athletes) {
                athlete.setRegistrationId(registration.getId());
                registrationWithAthleteMapper.updateRegistrationWithAthlete(athlete);
            }
            log.info("报名信息已更新: {}, {}", registration, athletes);
        }
    }

    public void deleteRegistration(Long id) {
        Registration registration = registrationMapper.selectRegistrationById(id);
        if (registration != null) {
            registrationMapper.deleteRegistration(id);
            registrationWithAthleteMapper.deleteRegistrationWithAthlete(id);
            log.info("报名信息已删除: {}", id);
        } else {
            log.info("此报名信息暂不存在!!!");
        }
    }

    public List<RegistrationVO> showSearchedRegistrations(RegistrationVO registrationCondition) {
        List<RegistrationVO> registrationVOS = new ArrayList<>();
        if (registrationCondition != null) {
            registrationVOS = registrationMapper.selectRegistrationVOByCondition(registrationCondition);
        }
        for (RegistrationVO registrationVO : registrationVOS) {
            RegistrationWithAthlete registrationWithAthleteCondition = new RegistrationWithAthlete();
            registrationWithAthleteCondition.setRegistrationId(registrationVO.getRegistrationId());
            List<RegistrationWithAthlete> athletes = registrationWithAthleteMapper.selectRegistrationWithAthleteByConditions(registrationWithAthleteCondition);
            registrationVO.setAthletes(athletes);
        }
        return registrationVOS;
    }

    public List<RegistrationWithAthlete> showAthleteNamesInRace(Long raceId, String teamName) {
        List<RegistrationWithAthlete> athletes = new ArrayList<>();
        RegistrationVO registrationVO = new RegistrationVO();
        registrationVO.setRaceId(raceId);
        registrationVO.setTeamName(teamName);
        List<RegistrationVO> registrationVOS = showSearchedRegistrations(registrationVO);
        for (RegistrationVO vo : registrationVOS) {
            athletes.addAll(vo.getAthletes());
        }
        log.info("队伍 {} 的参赛队员有： {}", teamName, athletes.size());
        return athletes;
    }

    public List<RegistrationExportData> getRegistrationExportData(RegistrationVO regCondition) {
        List<RegistrationExportData> exportDataList = new ArrayList<>();
        List<RegistrationVO> registrationVOS = showSearchedRegistrations(regCondition);
        for (RegistrationVO registrationVO : registrationVOS) {
            List<String> group1 = new ArrayList<>(); // 甲组
            List<String> group2 = new ArrayList<>(); // 乙组
            List<String> group3 = new ArrayList<>(); // 丙组
            List<String> group4 = new ArrayList<>(); // 默认组
            for (RegistrationWithAthlete athlete : registrationVO.getAthletes()) {
                log.info("athlete的值为：{}", athlete);
                AthleteVO athleteVO = new AthleteVO();
                athleteVO.setId(athlete.getAthleteId());
                List<AthleteVO> athleteVOS = teamInfoService.showSearchedAthletes(athleteVO);
                AthleteVO athleteVO1 = athleteVOS.get(0);
                if (athleteVO1.getCategory().startsWith("甲")) {
                    group1.add(athleteVO1.getName());
                } else if (athleteVO1.getCategory().startsWith("乙")) {
                    group2.add(athleteVO1.getName());
                }else if (athleteVO1.getCategory().startsWith("丙")) {
                    group3.add(athleteVO1.getName());
                }else {
                    group4.add(athleteVO1.getName());
                }
            }
            if (!group1.isEmpty()) {
                RegistrationExportData exportData1 = new RegistrationExportData("甲组",
                        registrationVO.getRace().getGenderEnum().getDisplayName(),
                        registrationVO.getRace().getName(), group1, registrationVO.getRace().getRaceType());
                exportDataList.add(exportData1);
            }

            if (!group2.isEmpty()) {
                RegistrationExportData exportData2 = new RegistrationExportData("乙组",
                        registrationVO.getRace().getGenderEnum().getDisplayName(),
                        registrationVO.getRace().getName(), group2, registrationVO.getRace().getRaceType());
                exportDataList.add(exportData2);
            }

            if (!group3.isEmpty()) {
                RegistrationExportData exportData3 = new RegistrationExportData("丙组",
                        registrationVO.getRace().getGenderEnum().getDisplayName(),
                        registrationVO.getRace().getName(), group3, registrationVO.getRace().getRaceType());
                exportDataList.add(exportData3);
            }

            if (!group4.isEmpty()) {
                RegistrationExportData exportData4 = new RegistrationExportData("",
                        registrationVO.getRace().getGenderEnum().getDisplayName(),
                        registrationVO.getRace().getName(), group4, registrationVO.getRace().getRaceType());
                exportDataList.add(exportData4);
            }
        }

        return aggregateExportData(exportDataList);
    }

    public List<RegistrationExportData> aggregateExportData(List<RegistrationExportData> dataList) {
        return dataList.stream()
                .collect(Collectors.groupingBy(
                        d -> new CompositeKey(d.getGroup(), d.getGender(), d.getRaceName(), d.getRaceType()),
                        Collectors.flatMapping(
                                d -> d.getAthleteNames().stream(),
                                Collectors.toList()
                        )
                ))
                .entrySet().stream()
                .map(entry -> new RegistrationExportData(
                        entry.getKey().getGroup(),
                        entry.getKey().getGender(),
                        entry.getKey().getRaceName(),
                        entry.getValue(),
                        entry.getKey().getRaceType()
                ))
                .collect(Collectors.toList());
    }
}
